<?php
/**
 * forumConnect Server for vBulletin (4.x)
 *
 * @category   forumConnect
 * @package    forumConnect_Server
 * @copyright  Copyright (c) 2010 Benjamin Clot (benjamin.clot@gmail.com)
 */

error_reporting(E_ALL & ~E_NOTICE);

define('NOSHUTDOWNFUNC', 1);
define('SKIP_SESSIONCREATE', 1);
define('DIE_QUIETLY', 1);
define('THIS_SCRIPT', 'forumConnect_Server_vBulletin4');
define('CSRF_PROTECTION', false);

$phrasegroups = array();
$specialtemplates = array();
$globaltemplates = array();
$actiontemplates = array();

require_once('./global.php');
require_once(DIR . '/includes/class_xml.php');

$vbulletin->input->clean_array_gpc('r', array(
	'do' => TYPE_NOHTML
));

/**
 * forumConnect_Server_vBulletin4
 *
 * @category   forumConnect
 * @package    forumConnect_Server
 * @subpackage vBulletin4
 * @copyright  Copyright (c) 2010 Benjamin Clot (benjamin.clot@gmail.com)
 */
final class forumConnect_Server_vBulletin4
{
	/**
	 * userinfo cache
	 *
	 * @var	array
	 */
	protected $_userinfocache = array();
	
	/**
	 * XML resource handler
	 *
	 * @var	resource
	 */
	public $xml;
	
	/**
	 * Constructor
	 */
	public function __construct()
	{
		$this->xml = new vB_XML_Builder($GLOBALS['vbulletin'], 'text/xml', 'UTF-8');
	}
	
	/**
	 * call - function caller
	 * 
	 * @param string
	 * @return void
	 */
	public function call($function)
	{
		if (in_array($function, array(
			'getthread',
			'getuser',
			'isloggedin'
		)))
		{
			call_user_func(array($this, '_' . $function));
		}
		else
		{
			$this->xml->add_tag('error', 'This function doesn\'t exist or is not available.');
			$this->xml->print_xml();
		}
	}
	
	/**
	 * _fetchpostorder - get post order (for threaded mode)
	 * 
	 * @return void
	 */
	protected function _fetchpostorder($parentid = 0, $depth = 0)
	{
		if (is_array($this->_ipost[$parentid]))
		{
			foreach ($this->_ipost[$parentid] AS $postid)
			{
				$this->_postorder[$postid] = $depth;
				$this->_fetchpostorder($postid, $depth + 1);
			}
		}
	}
	
	/**
	 * _fetchuser - fetch user details
	 *
	 * @param	int	userid
	 * @param string username (only used if userid is null like for anonymous posts)
	 * @return void
	 */
	protected function _fetchuser($userid, $username = '')
	{
		if ($userid)
		{
			if (isset($this->_userinfocache[$userid]))
			{
				$userinfo = $this->_userinfocache[$userid];
			}
			else
			{
				$userinfo = verify_id('user', $userid, false, true, 2);
				cache_permissions($userinfo, false, false);
				
				$this->_userinfocache[$userid] = $userinfo;
			}
		}
		
		$this->xml->add_group('user');
		
		if (!empty($userinfo))
		{
			$this->xml->add_tag('userid', $userinfo['userid']);
			$this->xml->add_tag('usergroupids', $userinfo['usergroupid'] . ($userinfo['membergroupids'] ? ',' . $userinfo['membergroupids'] : ''));
			$this->xml->add_tag('username', utf8_encode($userinfo['username']));
			$this->xml->add_tag('usertitle', $userinfo['customtitle'] ? utf8_encode($userinfo['usertitle']) : '');
			$this->xml->add_tag('email', $userinfo['email']);
			
			if ($userinfo['avatarid'])
			{
				$this->xml->add_tag('avatarurl', $userinfo['avatarpath']);
			}
			else
			{
				if ($userinfo['hascustomavatar'] AND $GLOBALS['vbulletin']->options['avatarenabled'] AND ($userinfo['permissions']['genericpermissions'] & $GLOBALS['vbulletin']->bf_ugp_genericpermissions['canuseavatar'] OR $userinfo['adminavatar']))
				{
					if ($vbulletin->options['usefileavatar'])
					{
						$this->xml->add_tag('avatarurl', $GLOBALS['vbulletin']->options['bburl'] . '/' . $GLOBALS['vbulletin']->options['avatarurl'] . '/avatar' . $userinfo['userid'] . '_' . $userinfo['avatarrevision'] . '.gif');
					}
					else
					{
						$this->xml->add_tag('avatarurl', $GLOBALS['vbulletin']->options['bburl'] . '/image.php?u=' . $userinfo['userid'] . '&amp;dateline=' . $userinfo['avatardateline'] . '&amp;type=thumb');
					}
				}
				else
				{
					$this->xml->add_tag('avatarurl', '');
				}
			}
			
			$this->xml->add_tag('logouthash', $userinfo['logouthash']);
			$this->xml->add_tag('isadmin', ($userinfo['permissions']['adminpermissions'] & $GLOBALS['vbulletin']->bf_ugp_adminpermissions['cancontrolpanel']) ? 1 : 0);
			$this->xml->add_tag('isbanned', !($GLOBALS['vbulletin']->usergroupcache[$userinfo['usergroupid']]['genericoptions'] & $GLOBALS['vbulletin']->bf_ugp_genericoptions['isnotbannedgroup']) ? 1 : 0);
			$this->xml->add_tag('isvalid', !in_array($userinfo['usergroupid'], array(3, 4)) ? 1 : 0);
		}
		else
		{
			$this->xml->add_tag('userid', 0);
			
			if ($username)
			{
				$this->xml->add_tag('username', utf8_encode($username));
			}
		}
		
		$this->xml->close_group('user');
	}
	
	/**
	 * _getthread - get thread details
	 * If getposts is TRUE, get the user details from the user tag inside the first post tag.
	 * If getposts is FALSE, get the user details from the user tag inside the thread tag.
	 * Threaded mode adds a depth tag inside the post tag.
	 * Posts are always returned in ascending order.
	 * 
	 * @return void
	 */
	protected function _getthread()
	{
		$GLOBALS['vbulletin']->input->clean_array_gpc('r', array(
			'getposts' => TYPE_BOOL,
			'threadid' => TYPE_UINT,
			'threaded' => TYPE_BOOL
		));
		
		$this->xml->add_group('thread');
		
		$threadinfo = verify_id('thread', $GLOBALS['vbulletin']->GPC['threadid'], false, true);
		
		if ($threadinfo)
		{
			require_once(DIR . '/includes/class_bbcode.php');
			
			$bbcode_parser = new vB_BbCodeParser($GLOBALS['vbulletin'], fetch_tag_list());
			
			require_once(CWD . '/includes/class_friendly_url.php');
			
			$this->xml->add_tag('threadid', $threadinfo['threadid']);
			$this->xml->add_tag('description', utf8_encode($bbcode_parser->parse($threadinfo['description'], false, false)));
			$this->xml->add_tag('title', utf8_encode($threadinfo['title']));
			$this->xml->add_tag('url', utf8_encode($GLOBALS['vbulletin']->options['bburl'] . '/' . vB_Friendly_Url::fetchLibrary($GLOBALS['vbulletin'], 'thread|nosession', $threadinfo)->get_url()));
			$this->xml->add_tag('firstpostid', $threadinfo['firstpostid']);
			$this->xml->add_tag('lastpostid', $threadinfo['lastpostid']);
			$this->xml->add_tag('forumid', $threadinfo['forumid']);
			$this->xml->add_tag('replycount', $threadinfo['replycount']);
			$this->xml->add_tag('lastusername', utf8_encode($threadinfo['lastposter']));
			$this->xml->add_tag('lastuserid', $threadinfo['lastposterid']);
			$this->xml->add_tag('dateline', $threadinfo['dateline']);
			$this->xml->add_tag('views', $threadinfo['views']);
			$this->xml->add_tag('votecount', $threadinfo['votenum']);
			$this->xml->add_tag('votetotal', $threadinfo['votetotal']);
			$this->xml->add_tag('isdeleted', $threadinfo['isdeleted']);
			$this->xml->add_tag('isopen', $threadinfo['open']);
			$this->xml->add_tag('issticky', $threadinfo['sticky']);
			$this->xml->add_tag('isvisible', $threadinfo['visible']);
			
			if ($GLOBALS['vbulletin']->GPC['getposts'])
			{
				require_once(DIR . '/includes/functions_bigthree.php');
				
				$coventry = fetch_coventry('string');
				
				$posts = $GLOBALS['vbulletin']->db->query_read("
					SELECT post.*, IF(post.visible = 2, 1, 0) AS isdeleted
					FROM " . TABLE_PREFIX . "post AS post
					WHERE post.threadid = " . $threadinfo['threadid'] . "
						" . ($coventry ? "AND post.userid NOT IN ($coventry)" : '') . "
					ORDER BY post.dateline ASC
				");
				
				$this->_post = array();
				$this->_ipost = array();
				$postdata = array();
				
				while ($post = $GLOBALS['vbulletin']->db->fetch_array($posts))
				{
					$this->_ipost[$post['parentid']][$post['postid']] = $post['postid'];
					$postdata[$post['postid']] = $post;
				}
				
				$GLOBALS['vbulletin']->db->free_result($posts);
				
				if ($GLOBALS['vbulletin']->GPC['threaded'])
				{
					$this->_postorder = array();
					$this->_fetchpostorder();
					
					foreach ($this->_postorder AS $postid => $depth)
					{
						$this->_post[$postid] = $postdata[$postid];
						$this->_post[$postid]['depth'] = $depth;
					}
				}
				else
				{
					$this->_post = $postdata;
				}
				
				require_once(DIR . '/includes/class_bbcode.php');
				
				$bbcode_parser = new vB_BbCodeParser($GLOBALS['vbulletin'], fetch_tag_list());
				
				require_once(CWD . '/includes/class_friendly_url.php');
				
				$this->xml->add_group('posts');
				
				foreach ($this->_post AS $postid => $post)
				{
					$this->xml->add_group('post');
						$this->xml->add_tag('postid', $postid);
						$this->xml->add_tag('parentid', $post['parentid']);
						$this->xml->add_tag('title', utf8_encode($post['title']));
						$this->xml->add_tag('dateline', $post['dateline']);
						$this->xml->add_tag('content',  utf8_encode($bbcode_parser->parse($post['pagetext'], false, false)));
						$this->xml->add_tag('url', utf8_encode($GLOBALS['vbulletin']->options['bburl'] . '/' . vB_Friendly_Url::fetchLibrary($GLOBALS['vbulletin'], 'thread|nosession', $threadinfo, array('p' => $postid))->get_url() . '#post' . $postid));
						$this->xml->add_tag('isdeleted', $post['isdeleted']);
						$this->xml->add_tag('isvisible', $post['visible']);
						
						if ($GLOBALS['vbulletin']->GPC['threaded'])
						{
							$this->xml->add_tag('depth', $post['depth']);
						}
						
						$this->_fetchuser($post['userid'], $post['username']);
						
					$this->xml->close_group('post');
				}
				
				$this->xml->close_group('posts');
			}
			else
			{
				$this->_fetchuser($threadinfo['postuserid'], $threadinfo['postusername']);
			}
		}
		else
		{
			$this->xml->add_tag('threadid', 0);
		}
		
		$this->xml->close_group('thread');
		$this->xml->print_xml();
	}
	
	/**
	 * _getuser - get user details
	 * 
	 * @return void
	 */
	protected function _getuser()
	{
		$GLOBALS['vbulletin']->input->clean_array_gpc('r', array(
			'userid' => TYPE_UINT
		));
		
		$this->_fetchuser($GLOBALS['vbulletin']->GPC['userid']);
		
		$this->xml->print_xml();
	}
	
	/**
	 * _isloggedin - check if user is logged in
	 * NB: ipaddress and useragent come from $_SERVER, the other variables come from the user's cookie.
	 * 
	 * @return void
	 */
	protected function _isloggedin()
	{
		$GLOBALS['vbulletin']->input->clean_array_gpc('r', array(
			'ipaddress' => TYPE_NOHTML,
			'sessionid' => TYPE_NOHTML,
			'sessionuser' => TYPE_NOHTML,
			'useragent' => TYPE_STR
		));
		
		list($userid, $password) = explode(',', $GLOBALS['vbulletin']->GPC['sessionuser'], 2);
		
		$this->xml->add_group('user');
		
		$idhash = md5($GLOBALS['vbulletin']->GPC['useragent'] . $GLOBALS['vbulletin']->session->fetch_substr_ip($GLOBALS['vbulletin']->GPC['ipaddress']));
		
		if ($GLOBALS['vbulletin']->GPC['sessionid'])
		{
			if ($session = $GLOBALS['vbulletin']->db->query_first_slave("
				SELECT *
				FROM " . TABLE_PREFIX . "session
				WHERE sessionhash = '" . $GLOBALS['vbulletin']->db->escape_string($GLOBALS['vbulletin']->GPC['sessionid']) . "'
					AND lastactivity > " . (TIMENOW - $GLOBALS['vbulletin']->options['cookietimeout']) . "
					AND idhash = '" . $GLOBALS['vbulletin']->db->escape_string($idhash) . "'
					AND userid > 0
			"))
			{
				$isloggedin = true;
			}
		}
		
		if (!$isloggedin AND $userid AND $password)
		{
			$userinfo = fetch_userinfo($GLOBALS['vbulletin']->GPC['userid']);
			
			if (md5($userinfo['password'] . COOKIE_SALT) == $password)
			{
				if ($GLOBALS['vbulletin']->GPC['sessionid'])
				{
					$GLOBALS['vbulletin']->db->query_write("
						DELETE FROM " . TABLE_PREFIX . "session
						WHERE sessionhash = '" . $vbulletin->db->escape_string($GLOBALS['vbulletin']->GPC['sessionid']). "'
					");
				}
				
				$session['sessionhash'] = md5(uniqid(microtime(), true));
				$session['userid'] = $userid;
				
				$isloggedin = true;
			}
		}
		
		if ($isloggedin)
		{
			$GLOBALS['vbulletin']->db->query_write("
				INSERT INTO " . TABLE_PREFIX . "session (sessionhash, userid, host, idhash, lastactivity, useragent, loggedin)
				VALUES ('" . $GLOBALS['vbulletin']->db->escape_string($session['sessionhash']) . "', " . $session['userid'] . ", '" . $GLOBALS['vbulletin']->db->escape_string(substr($GLOBALS['vbulletin']->GPC['ipaddress'], 0, 15)) . "', '" . $GLOBALS['vbulletin']->db->escape_string($idhash) . "', " . TIMENOW . ", '" . $GLOBALS['vbulletin']->db->escape_string($GLOBALS['vbulletin']->GPC['useragent']) . "', 1)
				ON DUPLICATE KEY UPDATE lastactivity = " . TIMENOW . "
			");
			
			$this->xml->add_tag('userid', $userinfo['userid']);
		}
		else
		{	
			$this->xml->add_tag('userid', 0);
		}
		
		$this->xml->close_group('user');
		$this->xml->print_xml();
	}
}

$forumConnect_Server_vBulletin4 = new forumConnect_Server_vBulletin4();
$forumConnect_Server_vBulletin4->call($vbulletin->GPC['do']);
